package com.hqyj.javaSpringBoot.modules.common.controller;

import com.hqyj.javaSpringBoot.modules.common.entity.ExceptionLog;
import com.hqyj.javaSpringBoot.modules.common.service.ExceptionLogService;
import org.apache.commons.lang3.StringUtils;
//import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class ExceptionHandleController {
    private final static Logger LOGGER=
            LoggerFactory.getLogger(ExceptionHandleController.class);

    @Autowired
    private ExceptionLogService exceptionLogService;

//    @ExceptionHandler(value = {ArithmeticException.class})
    @ExceptionHandler(value = {Exception.class})
    //ModelAndView
    public ModelAndView exceptionHandle(HttpServletRequest request, Exception e) {
        LOGGER.debug("=====Catch Exception =======");
        LOGGER.debug(e.getMessage());
        e.printStackTrace();
        //根据异常的类型确定状态值、错误路径、错误信息--------403||500

        HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        String errorPath = "/common/500";
        String message="Internal Server Error";
        //先假定ArithmeticException是没有权限异常
        if (e instanceof UnauthorizedException) {
            httpStatus = HttpStatus.FORBIDDEN;
            errorPath = "/common/403";
            message="No permission.";
        }
        //保存异常信息
        saveExceptionLog(request,e);
        //在异常类型确定状态值
        if (isInterface(request)){
            //返回json数据
            return   returnJson(errorPath,httpStatus,message);
        }else {
            //返回错误页面
            return returnView(errorPath,httpStatus);
        }


        //判断访问view还是数据接口

        // 如果是view则返回
    }

    //返回json
    private ModelAndView returnJson(String path,HttpStatus httpStatus,String message){
        ModelAndView modelAndView=new ModelAndView(new MappingJackson2JsonView());
        modelAndView.addObject("status",httpStatus.value());
        modelAndView.addObject("message",message);
        modelAndView.addObject("object",path);
        return modelAndView;
    }

    //返回view
    private ModelAndView returnView(String path,HttpStatus httpStatus){
        return new ModelAndView("redirect:"+path,httpStatus);
    }

    //判断是否为接口
    private boolean isInterface(HttpServletRequest request){
        HandlerMethod handlerMethod=(HandlerMethod) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingHandler");
        if (handlerMethod==null){
            return false;
        }
        ResponseBody[] methodAnnotations=
                handlerMethod.getMethod().getAnnotationsByType(ResponseBody.class);
        ResponseBody[] typeAnnotations1 = handlerMethod.getBeanType().getAnnotationsByType(ResponseBody.class);
        RestController[] typeAnnotations2 = handlerMethod.getBeanType().getAnnotationsByType(RestController.class);
        return methodAnnotations.length>0||
                typeAnnotations1.length>0||
                typeAnnotations2.length>0;

    }

    //保存异常信息
    private void saveExceptionLog(HttpServletRequest request,Exception e){
        ExceptionLog  exceptionLog=new ExceptionLog();
        exceptionLog.setIp(request.getRemoteAddr());
        exceptionLog.setPath(request.getRequestURI());
        HandlerMethod handlerMethod= (HandlerMethod) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingHandler");
        if (handlerMethod!=null){
            exceptionLog.setClassName(handlerMethod.getBeanType().getName());
            exceptionLog.setMethodName(handlerMethod.getMethod().getName());

        }
        exceptionLog.setExceptionType(e.getClass().getSimpleName());
        exceptionLog.setExceptionMessage(StringUtils.isBlank(e.getMessage())?"":
                e.getMessage().substring(0,e.getMessage().length()>200?200:e.getMessage().length()));
    }
}
